#include "ship.h"
#include "physics/physicsworld.h"

void Ship::Initialise( gecko::IEffect* effect )
{
	m_mesh = new gecko::Geometry;
	m_mesh->CreateTriangle(gecko::Vector3f(-0.1f, -0.1f, 0.0f), gecko::Vector3f(0.1f, -0.1f, 0.0f), gecko::Vector3f(0.0f, 0.2f, 0.0f), gecko::Colour::Random().ToInt(), effect);

	m_turnRate = 0.0f;
	m_bodyForces.Zero();
	m_mass = 1.0f;
	m_zoomDistance = 10.0f;

	m_turnRate = 0.0f;
	m_zoom = 0.0f;
	m_thrust = 0.0f;
}

void Ship::InitialisePhysics( gecko::PhysicsWorld & physicsWorld )
{
	gecko::ShapeDef polyShape;
	polyShape.Type = gecko::ShapeDef::Type_Poly;
	polyShape.Density = 1.0f;
	polyShape.PolyVerts[0] = gecko::Vector3f(-0.1f, -0.1f, 0.0f);
	polyShape.PolyVerts[1] = gecko::Vector3f(0.1f, -0.1f, 0.0f);
	polyShape.PolyVerts[2] = gecko::Vector3f(0.0f, 0.2f, 0.0f);
	polyShape.NumVerts = 3;
	polyShape.Offset = gecko::Vector3f();

	gecko::BodyDef bodyDef;
	bodyDef.BodyType = gecko::BodyDef::Type_Dynamic;
	bodyDef.Restitution = 0.1f;
	bodyDef.Friction = 1.0f;
	bodyDef.FixedRotation = false;
	bodyDef.SpriteOffset = gecko::Vector3f();
	bodyDef.Shapes[0] = polyShape;
	bodyDef.NumShapes = 1;

	// create body
	m_body = physicsWorld.CreatePhysicsObject(bodyDef, gecko::Vector3f(0.0f, 0.0f, 0.0f));
}

void Ship::DoThrust(float value)
{
	static const float PAD_THRUST = 0.1f;
	m_thrust = value * PAD_THRUST;
}

void Ship::Turn(float value)
{
	static const float PAD_TURN_RATE = 5.0f;
	m_turnRate = -value * PAD_TURN_RATE;
}

gecko::Entity::UpdateReturn Ship::Update( float dt )
{
	// all the control stuff is a shitty hack and should not be done like this going forward..
	// what we want to do is use forces to control the ship
	// but this is just to get things working quickly...

	float physicsBodyAngle = m_body->GetRotation();

	if (fabs(m_turnRate) > 0.0f)
	{
		// stop rotation
		m_body->m_body->SetAngularVelocity(0.0f);
	}

	// apply rotation
	m_heading = physicsBodyAngle;
	m_heading += m_turnRate * dt;
	
	// setup rotation matrix
	gecko::Matrix44 rotation;
	rotation.SetupRotationZ(m_heading);

	// get thrust direction vector
	gecko::Vector3f direction;
	gecko::VectorMultiply(direction, gecko::Vector3f(0.0f, 1.0f, 0.0f), rotation);
	direction.Normalise();

	// apply forces		
	m_bodyForces += direction * m_thrust;

	// setup translation matrix
	gecko::Matrix44 translation;
	gecko::Vector3f myPosition;
	m_body->GetPosition(myPosition);
	translation.SetPosition(myPosition);

	m_body->m_body->SetTransform(b2Vec2(myPosition.x, myPosition.y), m_heading);

	// set the transform
	m_transform = rotation * translation;

	m_body->ApplyForce(m_bodyForces, myPosition);

	// clear out forces
	m_bodyForces.Zero();

	m_turnRate = 0.0f;
	m_zoom = 0.0f;
	m_thrust = 0.0f;

	// update base class
	return GameEntity::Update(dt);
}

void Ship::Render( gecko::IRenderer * renderer )
{
	//gecko::Vector3f zoomFactor = gecko::Vector3f(0.0f, 0.0f, m_zoomDistance);

	//gecko::Vector3f myPosition;
	//m_body->GetPosition(myPosition);

	//renderer->SetCamera(myPosition + zoomFactor, myPosition, gecko::Vector3f(0.0f, 1.0f, 0.0f), 45.0f);

	// setup geometry batching
	m_geometryInstance.m_Geometry = m_mesh;
	m_geometryInstance.Tranform = m_transform;

	// send it to the batcher
	renderer->AddBatchedGeometry(&m_geometryInstance);
}

